/*
 * Copyright (c) 2011 Denis Tulskiy
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with this work.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.tulskiy.keymaster.x11;

import com.sun.jna.platform.unix.X11;
import com.sun.jna.platform.unix.X11.Display;
import com.sun.jna.platform.unix.X11.KeySym;
import com.tulskiy.keymaster.common.MediaKey;

//import javax.swing.*;
//import java.awt.event.InputEvent;
//import com.tulskiy.keymaster.common.InputEvent;
//import javafx.scene.input.KeyCode;
//import javafx.scene.input.KeyCombination;

import com.tulskiy.keymaster.input.KeyCode;
import com.tulskiy.keymaster.input.KeyCombination;

import java.util.HashMap;

import static com.tulskiy.keymaster.x11.KeySymDef.*;
//import static java.awt.event.KeyEvent.*;
import static com.tulskiy.keymaster.input.KeyCode.*;

/**
 * Author: Denis Tulskiy
 * Date: 6/13/11
 */
class KeyMap {
    private static final HashMap<Integer, Integer> common = new HashMap<Integer, Integer>() {{
        put(ESCAPE.getCode(), XK_Escape);
        put(BACK_SPACE.getCode(), XK_BackSpace);
        put(TAB.getCode(), XK_Tab);
        put(ENTER.getCode(), XK_Return);
        put(PAUSE.getCode(), XK_Pause);
        put(SCROLL_LOCK.getCode(), XK_Scroll_Lock);
        put(DELETE.getCode(), XK_Delete);
        put(CLEAR.getCode(), XK_Clear);
        put(HOME.getCode(), XK_Home);
        put(LEFT.getCode(), XK_Left);
        put(UP.getCode(), XK_Up);
        put(RIGHT.getCode(), XK_Right);
        put(DOWN.getCode(), XK_Down);
        put(PAGE_UP.getCode(), XK_Page_Up);
        put(PAGE_DOWN.getCode(), XK_Page_Down);
        put(END.getCode(), XK_End);
        put(BEGIN.getCode(), XK_Begin);
        put(KP_DOWN.getCode(), XK_KP_Down);
        put(KP_UP.getCode(), XK_KP_Up);
        put(KP_LEFT.getCode(), XK_KP_Left);
        put(KP_RIGHT.getCode(), XK_KP_Right);
        put(SPACE.getCode(), XK_space);
        put(EXCLAMATION_MARK.getCode(), XK_exclam);
        put(QUOTEDBL.getCode(), XK_quotedbl);
        put(NUMBER_SIGN.getCode(), XK_numbersign);
        put(DOLLAR.getCode(), XK_dollar);
        put(AMPERSAND.getCode(), XK_ampersand);
        put(LEFT_PARENTHESIS.getCode(), XK_parenleft);
        put(RIGHT_PARENTHESIS.getCode(), XK_parenright);
        put(ASTERISK.getCode(), XK_asterisk);
        put(PLUS.getCode(), XK_plus);
        put(COMMA.getCode(), XK_comma);
        put(MINUS.getCode(), XK_minus);
        put(PERIOD.getCode(), XK_period);
        put(SLASH.getCode(), XK_slash);
        put(COLON.getCode(), XK_colon);
        put(SEMICOLON.getCode(), XK_semicolon);
        put(LESS.getCode(), XK_less);
        put(EQUALS.getCode(), XK_equal);
        put(GREATER.getCode(), XK_greater);
        put(AT.getCode(), XK_at);
        put(BRACELEFT.getCode(), XK_braceleft);
        put(BRACERIGHT.getCode(), XK_braceright);
        put(BACK_SLASH.getCode(), XK_backslash);
        put(CIRCUMFLEX.getCode(), XK_asciicircum);
        put(UNDERSCORE.getCode(), XK_underscore);
        put(BACK_QUOTE.getCode(), XK_grave);
        put(DIVIDE.getCode(), XK_KP_Divide);
        put(MULTIPLY.getCode(), XK_KP_Multiply);
        put(INSERT.getCode(), XK_Insert);
        put(ADD.getCode(), XK_KP_Add);
        put(SUBTRACT.getCode(), XK_KP_Subtract);
        put(BEGIN.getCode(), XK_KP_Begin);
        put(PRINTSCREEN.getCode(), XK_Print);
        put(XF86XK_AudioNext, XF86XK_AudioNext);
        put(XF86XK_AudioPlay, XF86XK_AudioPlay);
        put(XF86XK_AudioPrev, XF86XK_AudioPrev);
        put(XF86XK_AudioStop, XF86XK_AudioStop);
    }};

    static byte getCode(KeyCode keyStroke, Display display) {
        //int code = keyStroke.getKeyCode();
        int code = keyStroke.getCode();

        int ret = -1;
        if ((code >= DIGIT0.getCode() && code <= DIGIT9.getCode()) || (code >= A.getCode() && code <= Z.getCode())) {
            ret = code;
        } else if (code >= F1.getCode() && code <= F12.getCode()) {
            ret = code - (F1.getCode() - XK_F1);
        } else if (code >= NUMPAD0.getCode() && code <= NUMPAD9.getCode()) {
            ret = code - (NUMPAD0.getCode() - XK_KP_0);
        } else {
            Integer i = common.get(code);
            if (i != null) {
                ret = i;
            }
        }

        if (ret != -1) {
            return X11.INSTANCE.XKeysymToKeycode(display, new KeySym(ret));
        } else {
            return 0;
        }
    }

    static byte getMediaCode(MediaKey mediaKey, Display display) {
        int code = 0;
        switch (mediaKey) {
            case MEDIA_NEXT_TRACK:
                code = XF86XK_AudioNext;
                break;
            case MEDIA_PLAY_PAUSE:
                code = XF86XK_AudioPlay;
                break;
            case MEDIA_PREV_TRACK:
                code = XF86XK_AudioPrev;
                break;
            case MEDIA_STOP:
                code = XF86XK_AudioStop;
                break;
        }
        return X11.INSTANCE.XKeysymToKeycode(display, new KeySym(code));
    }

    static int getModifiers(KeyCombination keyCode) {
        /**
         * liubinghua modified on 2023-11-07 23:05:05
         */
        int modifiers = 0;
        /*if ((keyCode.getModifiers() & InputEvent.SHIFT_DOWN_MASK) != 0) {
            modifiers |= X11.ShiftMask;
        }
        if ((keyCode.getModifiers() & InputEvent.CTRL_DOWN_MASK) != 0) {
            modifiers |= X11.ControlMask;
        }
        if ((keyCode.getModifiers() & InputEvent.META_DOWN_MASK) != 0) {
            modifiers |= X11.Mod4Mask;
        }
        if (keyCode.getModifiers() & InputEvent.ALT_DOWN_MASK != 0) {
            modifiers |= X11.Mod1Mask;
        }*/

        if (keyCode.getShift() == KeyCombination.ModifierValue.DOWN) {
            modifiers |= X11.ShiftMask;
        }
        if (keyCode.getControl() == KeyCombination.ModifierValue.DOWN) {
            modifiers |= X11.ControlMask;
        }
        if (keyCode.getMeta() == KeyCombination.ModifierValue.DOWN) {
            modifiers |= X11.Mod4Mask;
        }
        if (keyCode.getAlt() == KeyCombination.ModifierValue.DOWN) {
            modifiers |= X11.Mod1Mask;
        }
        return modifiers;
    }
}
